<!-- f:\1\shegongbu-web\src\views\system\menu\index.vue -->
<template>
  <div class="menu-page art-full-height">
    <!-- 搜索栏 -->
    <ArtSearchBar
      v-model="searchForm"
      :items="formItems"
      :showExpand="false"
      @reset="handleReset"
      @search="handleSearch"
    />

    <ElCard class="art-table-card" shadow="never">
      <!-- 表格头部 -->
      <ArtTableHeader
        :showZebra="false"
        :loading="loading"
        v-model:columns="columnChecks"
        @refresh="refreshData"
      >
        <template #left>
          <ElButton @click="handleAddMenu" v-ripple>添加菜单</ElButton>
        </template>
      </ArtTableHeader>

      <!-- 表格 -->
      <ArtTable
        ref="tableRef"
        rowKey="id"
        :loading="loading"
        :columns="columns"
        :data="filteredTableData"
        :stripe="false"
        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
        :default-expand-all="false"
      />

      <!-- 菜单新增弹窗 -->
      <MenuAddDialog
        v-if="!isEditMode"
        v-model:visible="dialogVisible"
        :type="dialogType"
        :lockType="lockMenuType"
        :menu-options="menuOptions"
        :parent-menu="parentMenu"
        @submit="handleSubmit"
        @closed="handleDialogClosed"
      />

      <!-- 菜单编辑弹窗 -->
      <MenuEditDialog
        v-else
        v-model:visible="dialogVisible"
        :type="dialogType"
        :editData="editData"
        :menu-options="menuOptions"
        @submit="handleSubmit"
        @refresh="refreshData"
        @closed="handleDialogClosed"
      />
    </ElCard>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, h, onMounted, onUnmounted } from 'vue'
import { ElMessage, ElMessageBox, ElTag } from 'element-plus'
import { formatMenuTitle } from '@/router/utils/utils'
import ArtButtonTable from '@/components/core/forms/art-button-table/index.vue'
import { useTableColumns } from '@/composables/useTableColumns'
import { useAuth } from '@/composables/useAuth'
import { useMenuStore } from '@/store/modules/menu'
import { useRouter } from 'vue-router'
import MenuAddDialog from './modules/menu-add-dialog.vue'
import MenuEditDialog from './modules/menu-edit-dialog.vue'
import {
  apiRbacMenuTreeDataUsingPost,
  apiRbacMenuDeleteDataUsingPost
} from '@/api'

defineOptions({ name: 'Menus' })

// 获取router和menuStore实例
const router = useRouter()
const menuStore = useMenuStore()  

// 防抖定时器
let refreshDebounceTimer: ReturnType<typeof setTimeout> | null = null
let syncDebounceTimer: ReturnType<typeof setTimeout> | null = null

// 添加组件挂载状态跟踪
const isMounted = ref(false)

const { hasAuth } = useAuth()

// 状态管理
const loading = ref(false)
const tableRef = ref()

// 弹窗相关
const dialogVisible = ref(false)
const dialogType = ref<'menu' | 'button'>('menu')
const editData = ref<any>(null)
const lockMenuType = ref(false)
const menuOptions = ref<any[]>([])
const isEditMode = ref(false)
const parentMenu = ref<any>(null)

// 搜索相关
const searchForm = reactive({
  name: '',
  route: ''
})

const formItems = computed(() => [
  {
    label: '菜单名称',
    key: 'name',
    type: 'input',
    props: { clearable: true }
  },
  {
    label: '路由地址',
    key: 'route',
    type: 'input',
    props: { clearable: true }
  }
])

// 菜单类型工具函数
const getMenuTypeTag = (row: any) => {
  if (!row) return 'info'
  if (row.menuType === 2) return 'danger' // 权限按钮
  if (row.children?.length) return 'info' // 目录
  if (row.menuFrameUrl && row.menuFrameFlag === 1) return 'success' // 内嵌
  if (row.menuPath) return 'primary' // 菜单
  if (row.menuFrameUrl) return 'warning' // 外链
  return 'info'
}

const getMenuTypeText = (row: any) => {
  if (!row) return '未知'
  if (row.menuType === 2) return '按钮'
  if (row.children?.length) return '目录'
  if (row.menuFrameUrl && row.menuFrameFlag === 1) return '内嵌'
  if (row.menuPath) return '菜单'
  if (row.menuFrameUrl) return '外链'
  return '未知'
}

// 表格列配置
const { columnChecks, columns } = useTableColumns(() => [
  {
    prop: 'menuName',
    label: '菜单名称',
    minWidth: 120,
    formatter: (row: any) => formatMenuTitle(row.menuName || '')
  },
  {
    prop: 'menuType',
    label: '菜单类型',
    formatter: (row: any) => {
      return h(ElTag, { type: getMenuTypeTag(row) }, () => getMenuTypeText(row))
    }
  },
  {
    prop: 'menuPath',
    label: '路由',
    formatter: (row: any) => {
      if (!row) return ''
      if (row.menuType === 2) return ''
      return row.menuFrameUrl || row.menuPath || ''
    }
  },
  {
    prop: 'menuWebPerms',
    label: '权限标识',
    formatter: (row: any) => {
      if (!row) return ''
      return row.menuWebPerms || ''
    }
  },
  {
    prop: 'menuSort',
    label: '排序',
    width: 80
  },
  {
    prop: 'menuVisibleFlag',
    label: '状态',
    formatter: (row: any) => {
      if (!row) return h(ElTag, { type: 'danger' }, () => '未知')
      const type = row.menuVisibleFlag === 1 ? 'success' : 'danger'
      const text = row.menuVisibleFlag === 1 ? '启用' : '禁用'
      return h(ElTag, { type }, () => text)
    }
  },
  {
    prop: 'operation',
    label: '操作',
    width: 180,
    align: 'right',
    formatter: (row: any) => {
      if (!row) return null
      const buttonStyle = { style: 'text-align: right' }

      if (row.menuType === 2) {
        return h('div', buttonStyle, [
          h(ArtButtonTable, {
            type: 'edit',
            onClick: () => handleEditAuth(row)
          }),
          h(ArtButtonTable, {
            type: 'delete',
            onClick: () => handleDeleteAuth(row)
          })
        ])
      }
      return h('div', buttonStyle, [
        h(ArtButtonTable, {
          type: 'add',
          onClick: () => handleAddChildMenu(row),
          title: '新增子菜单'
        }),
        h(ArtButtonTable, {
          type: 'edit',
          onClick: () => handleEditMenu(row)
        }),
        h(ArtButtonTable, {
          type: 'delete',
          onClick: () => handleDeleteMenu(row)
        })
      ])
    }
  }
])

// 数据相关
const tableData = ref<any[]>([])

// 事件处理
const handleReset = () => {
  searchForm.name = ''
  searchForm.route = ''
  refreshData()
}

const handleSearch = () => {
  refreshData()
}

const refreshData = () => {
  // 防抖
  if (refreshDebounceTimer) {
    clearTimeout(refreshDebounceTimer)
  }
  
  refreshDebounceTimer = setTimeout(async () => {
    loading.value = true
    try {
      const res = await apiRbacMenuTreeDataUsingPost({
        params: { pointsFlag: 1 }
      })
      
      // 统一处理API响应格式
      const menuData = processApiResponse(res)
      tableData.value = menuData
      menuOptions.value = flattenMenuTree(menuData)
    } catch (error: any) {
      ElMessage.error('获取菜单数据失败: ' + (error.message || '未知错误'))
      tableData.value = []
      menuOptions.value = []
    } finally {
      loading.value = false
    }
  }, 300) 
}

// 提取API响应处理逻辑
const processApiResponse = (res: any): any[] => {
  if (!res) {
    return []
  }
  
  // 处理标准响应格式
  if (res.code === 0 && Array.isArray(res.data)) {
    return res.data
  }
  
  // 处理直接返回数组的情况
  if (Array.isArray(res)) {
    return res
  }
  
  // 处理其他可能的成功格式
  if (res.hasOwnProperty('data') && Array.isArray(res.data)) {
    return res.data
  }
  
  return []
}

const flattenMenuTree = (menuTree: any[], result: any[] = []): any[] => {
  if (!Array.isArray(menuTree)) {
    return result
  }
  menuTree.forEach(menu => {
    if (!menu) return
    if (menu.menuType !== 2) {
      result.push({
        id: menu.id,
        menuName: menu.menuName,
        menuPath: menu.menuPath
      })
    }
    if (menu.children && Array.isArray(menu.children) && menu.children.length > 0) {
      flattenMenuTree(menu.children, result)
    }
  })
  return result
}

// 搜索过滤函数
const searchMenu = (items: any[]): any[] => {
  if (!Array.isArray(items)) {
    return []
  }
  
  return items.reduce((results: any[], item) => {
    if (!item) return results
    
    const searchName = searchForm.name?.toLowerCase().trim() || ''
    const searchRoute = searchForm.route?.toLowerCase().trim() || ''
    const menuTitle = (item.menuName || '').toLowerCase()
    const menuPath = (item.menuPath || '').toLowerCase()
    const nameMatch = !searchName || menuTitle.includes(searchName)
    const routeMatch = !searchRoute || menuPath.includes(searchRoute)

    if (item.children && Array.isArray(item.children) && item.children.length > 0) {
      const matchedChildren = searchMenu(item.children)
      if (matchedChildren.length > 0) {
        results.push({ ...item, children: matchedChildren })
        return results
      }
    }

    if (nameMatch && routeMatch) {
      results.push({ ...item })
    }
    return results
  }, [])
}

const filteredTableData = computed(() => {
  return searchMenu(tableData.value)
})

// 弹窗操作处理
const handleAddMenu = () => {
  resetDialogState()
  dialogType.value = 'menu'
  isEditMode.value = false  // 确保设置为新增模式
  dialogVisible.value = true
}

const handleAddChildMenu = (parentMenuData: any) => {
  if (!parentMenuData) return
  resetDialogState()
  parentMenu.value = parentMenuData
  dialogType.value = 'menu'
  isEditMode.value = false  // 确保设置为新增模式
  dialogVisible.value = true
}

const handleAddAuth = () => {
  resetDialogState()
  dialogType.value = 'button'
  isEditMode.value = false  // 确保设置为新增模式
  dialogVisible.value = true
}

const handleEditMenu = (row: any) => {
  if (!row) return
  resetDialogState()
  editData.value = row
  dialogType.value = 'menu'
  lockMenuType.value = true
  isEditMode.value = true  // 明确设置为编辑模式
  dialogVisible.value = true
}

const handleEditAuth = (row: any) => {
  if (!row) return
  resetDialogState()
  editData.value = row
  dialogType.value = 'button'
  isEditMode.value = true  // 明确设置为编辑模式
  dialogVisible.value = true
}

// 提取对话框状态重置逻辑
const resetDialogState = () => {
  // 重置所有相关状态
  isEditMode.value = false
  parentMenu.value = null
  lockMenuType.value = false
  editData.value = null
  dialogType.value = 'menu'
}

// 修改 handleSubmit 方法
const handleSubmit = () => {
  dialogVisible.value = false  // 关闭对话框
  refreshData()
  syncMenuStore()
}

// 在 handleClosed 事件中也确保状态被重置
const handleDialogClosed = () => {
  resetDialogState()
}

// 同步菜单数据到menuStore
const syncMenuStore = async () => {
  if (syncDebounceTimer) {
    clearTimeout(syncDebounceTimer)
  }
  
  syncDebounceTimer = setTimeout(async () => {
    // 检查组件是否仍然挂载
    if (!isMounted.value) {
      return
    }
    
    try {
      console.log('[Menu Sync] 开始同步菜单数据到store');
      menuStore.removeAllDynamicRoutes();
      console.log('[Menu Sync] 已移除所有动态路由');
      
      // 重新获取菜单数据
      const res = await apiRbacMenuTreeDataUsingPost({
        params: { pointsFlag: 1 },
      });
      
      console.log('[Menu Sync] 获取到的API数据:', res);
      
      // 复用API响应处理逻辑
      const menuListData = processApiResponse(res);
      console.log('[Menu Sync] 处理后的菜单数据:', menuListData);
      
      const menuList = convertToAppRouteRecord(menuListData);
      console.log('[Menu Sync] 转换后的路由配置:', menuList);
      
      menuStore.setMenuList(menuList);
      
      // 重新注册动态路由
      if (menuList.length > 0 && router) {
        try {
          const { registerDynamicRoutes } = await import('@/router/utils/registerRoutes');
          console.log('[Menu Sync] 开始注册动态路由');
          registerDynamicRoutes(router, menuList);
          console.log('[Menu Sync] 动态路由注册完成');
        } catch (e) {
          console.error('[Menu Sync] 路由注册失败:', e);
          ElMessage.error('路由注册失败：' + (e.message || '未知错误'));
        }
      }
    } catch (error) {
      console.error('[Menu Sync] 菜单同步失败:', error);
      ElMessage.error('菜单同步失败: ' + (error.message || '未知错误'));
    }
  }, 300) 
}

// 将API返回的数据转换为AppRouteRecord格式
const convertToAppRouteRecord = (data: any[]): any[] => {
  if (!Array.isArray(data)) {
    return []
  }
  
  const nameMap = new Map<string, number>()

  const generateUniqueName = (baseName: string, id: number | string): string => {
    const safeName = baseName
      .replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, '_')
      .replace(/_{2,}/g, '_')
      .replace(/^_|_$/g, '')
    
    const uniqueName = safeName ? `${safeName}_${id}` : `menu_${id}`
    return uniqueName
  }

  // 定义特殊路径映射
  const pathToComponentMap: Record<string, string> = {
    '/system/config': '@/views/system/configuration/index.vue',
    '/area/areaIndex': '@/views/area/index.vue',
    '/actManage/actIndex': '@/views/actManage/index.vue',
    '/postStation/postStationIndex': '@/views/postStation/index.vue',
    '/ticket/TicketIndex': '@/views/ticket/index.vue',
    '/help/HelpRecord': '@/views/help/record.vue',
    '/userarea/userarea': '@/views/userarea/list/index.vue'
  }

  const convert = (items: any[]): any[] => {
    return items.map(item => {
      if (!item) return null
      
      const isHide = item.menuVisibleFlag === 0
      let component = item.menuComponent || ''

      // 规范化路径处理
      if (!component && item.menuPath) {
        const cleanPath = item.menuPath.replace(/^\/+/, '')
        
        // 检查是否有特殊路径映射
        if (pathToComponentMap[item.menuPath]) {
          component = pathToComponentMap[item.menuPath];
        } 
        // 为一级菜单使用 Layout 组件而不是试图查找不存在的 index.vue
        else if (item.children && item.children.length > 0) {
          component = 'Layout'
        } else {
          // 对于没有显式指定组件的叶子节点，使用默认路径
          component = `@/views/${cleanPath}${cleanPath.endsWith('/index') ? '' : '/index'}.vue`
        }
        console.log(`[Menu Sync] 为路径 "${item.menuPath}" 自动生成组件路径: ${component}`);
      }

      const uniqueName = generateUniqueName(item.menuName || item.menuPath || 'menu', item.id)

      const converted: any = {
        id: item.id,
        path: item.menuPath || '',
        name: uniqueName,
        component: component,
        meta: {
          title: item.menuName || '',
          icon: item.menuIcon,
          sort: item.menuSort,
          visibleFlag: item.menuVisibleFlag,
          frameFlag: item.menuFrameFlag,
          frameUrl: item.menuFrameUrl,
          webPerms: item.menuWebPerms,
          apiPerms: item.menuApiPerms,
          disabledFlag: item.menuDisabledFlag,
          isHide: isHide
        }
      }

      // 添加调试信息
      console.log(`[Menu Sync] 转换菜单项:`, {
        id: item.id,
        name: item.menuName,
        path: item.menuPath,
        component: component,
        converted: converted
      });

      if (item.children && Array.isArray(item.children) && item.children.length > 0) {
        converted.children = convert(item.children)
      }

      return converted
    }).filter(item => item !== null) as any[]
  }

  const result = convert(data)
  return result
}


const handleDelete = async (row: any, type: 'menu' | 'auth') => {
  // 增加参数校验
  if (!row || !row.id) {
    ElMessage.error(`无效的${type === 'menu' ? '菜单' : '权限'}数据`)
    return
  }
  
  try {
    await ElMessageBox.confirm(`确定要删除该${type === 'menu' ? '菜单' : '权限'}吗？删除后无法恢复`, '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
    const res = await apiRbacMenuDeleteDataUsingPost({
      body: { id: row.id }
    })
    
    // 统一处理API响应
    if (isApiResponseSuccess(res)) {
      ElMessage.success('删除成功')
      refreshData()
      syncMenuStore()
    } else {
      const errorMsg = getApiErrorMessage(res) || `${type === 'menu' ? '菜单' : '权限'}删除失败`
      ElMessage.error(errorMsg)
    }
  } catch (error: any) {
    if (error !== 'cancel') {
      ElMessage.error(`删除失败: ${error.message || '未知错误'}`)
    }
  }
}

const handleDeleteMenu = (row: any) => handleDelete(row, 'menu')
const handleDeleteAuth = (row: any) => handleDelete(row, 'auth')

// 提取API响应判断逻辑
const isApiResponseSuccess = (res: any): boolean => {
  return res === true || (res && typeof res === 'object' && (res.code === 0 || res.success === true))
}

const getApiErrorMessage = (res: any): string | null => {
  if (res && typeof res === 'object') {
    if (res.msg) return res.msg
    if (res.message) return res.message
  }
  return null
}

onMounted(() => {
  isMounted.value = true
  refreshData()
})

// 组件卸载时清理定时器
onUnmounted(() => {
  isMounted.value = false
  if (refreshDebounceTimer) {
    clearTimeout(refreshDebounceTimer)
  }
  if (syncDebounceTimer) {
    clearTimeout(syncDebounceTimer)
  }
})
</script>

<style lang="scss" scoped>
.menu-page {
  .svg-icon {
    width: 1.8em;
    height: 1.8em;
    overflow: hidden;
    vertical-align: -8px;
    fill: currentcolor;
  }

  :deep(.small-btn) {
    height: 30px !important;
    padding: 0 10px !important;
    font-size: 12px !important;
  }
}
</style>